<?php
/**
 * Created by PhpStorm.
 * User: 小蛮哼哼哼
 * Email: 243194993@qq.com
 * Date: 2022/2/25
 * Time: 11:10
 * motto: 现在的努力是为了小时候吹过的牛逼！
 */

declare(strict_types=1);

namespace app\common\lib;

use think\Exception;
use think\facade\Log;

class Sign
{
    static private $_instance;

    /**
     * @return mixed
     */
    static public function getInstance()
    {
        if (empty(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    protected array $config = [];
    protected array $data = [];
    protected string $url = "https://open.jixuantiant.com/";

    public function __construct(array $config = [])
    {
        if (empty($config)) {
            $this->config = [
                "openid" => "2022022511161648100985",
                "seat" => "9pmcroothiwwgks08ocwcg8k8",
                "machine_id" => "4004701676"
            ];
        } else {
            $this->config = $config;
        }
    }

    /**
     * @param array $data
     * @param string $path
     * @return bool|string
     * @throws Exception
     */
    public function __post(array $data = [], string $path = "")
    {
        $this->data = $data;
        $this->__common();
        //加密
        $sign = $this->__MD5Sign($data);
        $this->data['sign'] = $sign;
        Log::info(json_encode($this->data));
        $result =  $this->__url($this->url . $path, $this->data);
        return json_decode($result,true);
    }

    /**
     * 公共
     */
    private function __common()
    {
        $this->data['openid'] = $this->config['openid'];
        $this->data['timestamp'] = time();
        $this->data['sign_type'] = 'md5';
    }

    /**
     * @param array $data
     * @return string
     */
    private function __MD5Sign(): string
    {
        if (!empty($this->data['sign'])) {
            unset($this->data['sign']);
        }
        //获取签名
        $string = $this->__getSignStr($this->data);

        $md5String = $string . "&key=" . $this->config['seat'];
        return md5($md5String);
    }

    /**
     * @param $data
     * @return string
     */
    private function __getSignStr($data): string
    {
        if (is_array($data)) {
            ksort($data);
        }

        // sign不参与签名
        unset($data['sign']);
        $str = '';
        foreach ($data as $key => $value) {
            $str .= "{$key}={$value}&";
        }

        return $str;
    }

    /**
     * @param string $url
     * @param array $data
     * @return bool|string
     * @throws Exception
     */
    private function __url(string $url = "", array $data = [])
    {
        $requestInfo = http_build_query($data);

        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Expect:'
        )); // 解决数据包大不能提交
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $requestInfo); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        $response = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            throw new Exception(curl_error($curl));
        }

        curl_close($curl); // 关键CURL会话
        return $response; // 返回数据
    }

}
